<?php
/**
 * Upload.php
 * @author    yejia <jia_ye@loongjoy.com>
 * @copyright Copyright (c) 2017 Loonjoy (http://www.loongjoy.com)
 * @version   v1.0.0
 */

namespace App\Utils;

use App\Models\System\File as FileModel;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Intervention\Image\Facades\Image;
use Loongjoy\SDK\Storage;
use OSS\Core\OssException;
use Throwable;

class Upload
{
    //上传图片格式
    public $imageAllowFiles = [
        '.png',
        '.jpg',
        '.jpeg',
        '.gif',
        '.bmp',
    ];

    //上传视频格式
    public $videoAllowFiles = [
        '.flv',
        '.swf',
        '.mkv',
        '.avi',
        '.rm',
        '.rmvb',
        '.mpeg',
        '.mpg',
        '.ogg',
        '.ogv',
        '.mov',
        '.wmv',
        '.mp4',
        '.webm',
        '.mp3',
        '.wav',
        '.mid',
    ];

    //上传文件格式
    public $fileAllowFiles = [
        '.png',
        '.jpg',
        '.jpeg',
        '.gif',
        '.bmp',
        '.flv',
        '.swf',
        '.mkv',
        '.avi',
        '.rm',
        '.rmvb',
        '.mpeg',
        '.mpg',
        '.ogg',
        '.ogv',
        '.mov',
        '.wmv',
        '.mp4',
        '.webm',
        '.mp3',
        '.wav',
        '.mid',
        '.rar',
        '.zip',
        '.tar',
        '.gz',
        '.7z',
        '.bz2',
        '.cab',
        '.iso',
        '.doc',
        '.docx',
        '.xls',
        '.xlsx',
        '.ppt',
        '.pptx',
        '.pdf',
        '.txt',
        '.md',
        '.xml',
        '.ipa',
        '.apk',
        '.plist',
        '.exe',
    ];

    /**
     * 上传文件大小
     * @var int
     */
    protected $maxFileSize;

    /**
     * 储存类型 (1-服务器 2-OSS)
     * @var int|mixed
     */
    protected $saveType;

    /**
     * 储存地点
     * @var string
     */
    protected $destination = null;

    public function __construct($type = 0, $size = 100 * 1024 * 1024)
    {
        $this->saveType = empty($type) ? config('app.fileSaveType', 1) : $type;

        switch ($this->saveType) {
            case 1:
                $this->destination = public_path('uploads');
                break;
            case 2:
                $this->destination = 'uploads';
                break;
        }

        $this->maxFileSize = $size;
    }

    /**
     * 上传图片
     * @param $files
     * @param null $size
     * @return JsonResponse|mixed
     * @throws Throwable
     */
    public function image($files, $size = null)
    {
        return $this->parseFile($files, $this->imageAllowFiles, $size);
    }

    /**
     * 上传视频
     * @param $files
     * @return JsonResponse|mixed
     * @throws Throwable
     */
    public function video($files)
    {
        return $this->parseFile($files, $this->videoAllowFiles);
    }

    /**
     * 上传文件
     * @param $files
     * @return JsonResponse|mixed
     * @throws Throwable
     */
    public function file($files)
    {
        return $this->parseFile($files, $this->fileAllowFiles);
    }

    /**
     * 上传核心
     * @param $files
     * @param $types
     * @param null $size
     * @return JsonResponse|mixed
     * @throws Throwable
     */
    private function parseFile($files, $types, $size = null)
    {
        if (empty($files) || empty(Arr::first($files))) {
            return Output::fail( '请选择上传文件');
        }

        $files = !is_array(Arr::first($files)) ? [Arr::first($files)] : Arr::first($files);
        DB::beginTransaction();
        try {
            $data = [];
            foreach ($files as $file) {
                $mimeType = $file->getClientMimeType();
                $mimeTypeArray = @explode('/', $mimeType);
                $nameArray = @explode('.', $file->getClientOriginalName());
                $suffix = strtolower(end($nameArray));

                $mimeTypeTmp = strtolower($mimeTypeArray[count($mimeTypeArray) - 1]);

                $fileSize = $file->getSize();
                if (!is_uploaded_file($file->getRealPath())) {
                    return Output::fail('上传文件不存在');
                }

                if ($fileSize > $this->maxFileSize) {
                    return Output::fail('文件大小超出限制' . round(($this->maxFileSize / 1024) / 1024, 2) . 'MB');
                }

                if (Arr::first($mimeTypeArray) == 'image' && $suffix == 'blob') {
                    $suffix = strtolower($mimeTypeTmp);
                }

                if (!in_array('.' . $suffix, $types)) {
                    return Output::fail('文件类型错误');
                }

                $fileName = str_replace('.', '', uniqid(mt_rand(10000, 99999), true)) . '.' . $suffix;
                $destination = $this->destination . '/' . date('Ymd');
                //图片裁剪
                $change = false;
                if (Arr::first($mimeTypeArray) == 'image') {
                    $img = Image::make($file->getRealPath());
                    // if (!empty($size) && count(explode('*', $size)) == 2) {
                    //     list($width, $height) = explode('*', $size);
                    //     if ($width < $img->getWidth() && $height < $img->getHeight()) {
                    //         $img->fit($width, $height)->save($file->getRealPath());
                    //     } else {
                    //         $img->save($file->getRealPath());
                    //     }
                    // } else {
//                    $exif = exif_read_data($file->getRealPath());
//                    if(!empty($exif['Orientation'])) {
//                        switch($exif['Orientation']) {
//                            case 8:
//                                $img = imagerotate($img,90,0);
//                                break;
//                            case 3:
//                                $img = imagerotate($img,180,0);
//                                break;
//                            case 6:
//                                $img = imagerotate($img,-90,0);
//                                break;
//                        }
//                    }
                    $img->save($file->getRealPath());
                    //}
                    $change = true;
                }
                if ($this->saveType == 1) {
                    //服务器存储
                    if (!File::isDirectory($destination)) {
                        File::makeDirectory($destination, 0777, true);
                    }

                    if (!$file->move($destination, $fileName)) {
                        return Output::fail('上传失败');
                    }

                    $savePath = str_replace(public_path(), '', $destination . '/' . $fileName);
                    $path = url($savePath);
                    $id = $this->save($fileName, $savePath, $file->getClientOriginalName(), $suffix, $mimeType, $fileSize);
                } else if ($this->saveType == 2) {
                    //oss存储
                    if ($change) {
                        $temp = public_path('uploads/tmp');
                        if (!File::isDirectory($temp)) {
                            File::makeDirectory($temp, 0777, true);
                        }

                        if (!$file->move($temp, $fileName)) {
                            return Output::fail('上传失败');
                        }


                        $oss = (new Storage('aliyun'))->uploadFile($destination . '/' . $fileName, $temp . '/' . $fileName);
                        File::deleteDirectory($temp);
                    } else {
                        $oss = (new Storage('aliyun'))->uploadFile($destination . '/' . $fileName, $file->getRealPath());
                    }
                    if (!Arr::get($oss, 'status')) {
                        return Output::fail('上传失败');
                    }
                    $savePath = '/' . $destination . '/' . $fileName;
                    $path = Arr::get($oss, 'url');
                    if (($index = strpos($path, '?')) > 0) {
                        $path = substr($path, 0, $index);
                    }

                    $id = $this->save($fileName, $savePath, $file->getClientOriginalName(), $suffix, $mimeType, $fileSize);
                } else {
                    return Output::fail('存储类型错误');
                }
                $data[] = ['id' => $id, 'title' => $fileName, 'src' => $path, 'oss' => !empty($oss) ? $oss : null, 'name_array' => $nameArray];
            }
            DB::commit();
            return Output::success('上传成功', $data);
        } catch (OssException $exception) {
            DB::rollback();
            var_dump($exception->getCode());
            var_dump($exception->getMessage());
            var_dump("detai:" . $exception->getDetails());
            var_dump("message:" . $exception->getErrorMessage());
            var_dump("getHTTPStatus:" . $exception->getHTTPStatus());
            var_dump($exception->getFile());
            return Output::error($exception,'上传文件');
        } catch (\Exception $exception) {
            DB::rollback();
            var_dump($exception->getCode());
            var_dump($exception->getMessage());
            var_dump($exception->getLine());
            var_dump($exception->getFile());

            return Output::error($exception,'上传文件');
        }
    }

    /**
     * 保存数据
     * @param $name
     * @param $path
     * @param $oldName
     * @param $suffix
     * @param $mimeType
     * @param $size
     * @return array
     */
    private function save($name, $path, $oldName, $suffix, $mimeType, $size)
    {
        return FileModel::insertGetId([
            'name' => $name,
            'path' => $path,
            'old_name' => $oldName,
            'suffix' => $suffix,
            'mime_type' => $mimeType,
            'size' => $size,
            'created_at' => time(),
            'type' => $this->saveType,
        ]);
    }
}
